package com.chenfan.process.service.impl;

import com.chenfan.infra.context.UserContextHolder;
import com.chenfan.notify.MessageClient;
import com.chenfan.process.biz.impl.NotifyBiz;
import com.chenfan.process.dto.ApprovalCallBack;
import com.chenfan.process.entity.po.*;
import com.chenfan.process.enums.ApprovalMessageTypeEnum;
import com.chenfan.process.enums.InstanceEnums;
import com.chenfan.process.event.callback.CallbackEvent;
import com.chenfan.process.service.*;
import com.chenfan.process.util.MessageCenterHelper;
import com.chenfan.process.util.TransactionUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;

/**
 * @author liuming
 * @date 2022/1/14
 */
@Service
@Slf4j
public class ApprovalDomainService {

    @Autowired
    private NotifyBiz notifyBiz;
    @Autowired
    private ApprovalService approvalService;
    @Autowired
    private ProcessDetailService processDetailService;
    @Autowired
    private ProcessInstanceApproveService processInstanceApproveService;
    @Autowired
    protected ApplicationEventPublisher publisher;
    @Autowired
    private ApprovalTemplateService approvalTemplateService;
    @Autowired
    private ProcessNodeNotifyConfigService processNodeNotifyConfigService;
    @Autowired
    private MessageClient messageClient;
    @Autowired
    private TemplateConfigService templateConfigService;

    public void refuse(ApprovalPo approvalPo, ProcessDetailPo processDetail, String remark) {

        approvalPo.refuse();
        // 更新审批单状态
        approvalService.updateById(approvalPo);

        // 更新Detail
        processDetail.refuse();
        processDetail.setRemark(remark);
        processDetailService.updateById(processDetail);

        // 更新instance
        processInstanceApproveService.updateApprovalAlone(approvalPo.getApprovalId(), InstanceEnums.REFUSE.getCode(), remark);
        notifyBiz.dealWithNotify(approvalPo.getApprovalId());
        sendRefuseMessage(approvalPo, processDetail);

        ApprovalCallBack.ApprovalCallBackBuilder builder = ApprovalCallBack.builder().approvalFlag(Boolean.FALSE);
        publishEvent(builder, approvalPo.getApprovalId(), Boolean.TRUE, Boolean.FALSE, null, null, null, remark);
    }

    protected void sendRefuseMessage(ApprovalPo approvalPo, ProcessDetailPo processDetail) {
        ApprovalTemplatePo templatePo = approvalTemplateService.getById(approvalPo.getApprovalTemplateId());
        TemplateConfigPo config = templateConfigService.getByTemplateId(approvalPo.getApprovalTemplateId(), approvalPo.getVersion());

        // 全局参数是否需要发送
        Boolean refuseNotify = config.getRefuseNotify();
        List<ProcessNodeNotifyConfig> nodeNotifyConfigList = processNodeNotifyConfigService.listWithProcessId(processDetail.getProcessId(), ApprovalMessageTypeEnum.APPROVAL_REFUSE);

        if (Boolean.FALSE.equals(refuseNotify) && CollectionUtils.isEmpty(nodeNotifyConfigList)) {
            return;
        }

        // 找到所有的messageKey, 如果节点中有对应的参数, 优先使用子节点的
        for (ProcessNodeNotifyConfig processNodeNotifyConfig : nodeNotifyConfigList) {
            // 检查下是否使用默认的模板
            //if (!ApprovalMessageTypeEnum.defaultValue(processNodeNotifyConfig.getMessageKey())) {}
            MessageCenterHelper.send(processNodeNotifyConfig.getMessageKey(), templatePo, approvalPo,
                    Lists.newArrayList(approvalPo.getCreateBy()), config, processDetail.getRemark());
            // 节点有对应的参数, 并且已经发送, 父节点无需再进行发送
            refuseNotify = Boolean.FALSE;
        }

        // 全局审批消息
        if  (Boolean.TRUE.equals(refuseNotify)) {
            //发送默认消息模板-审批拒绝通知
            MessageCenterHelper.sendDefault(ApprovalMessageTypeEnum.APPROVAL_REFUSE, templatePo, approvalPo,
                    Lists.newArrayList(approvalPo.getCreateBy()), config, processDetail.getRemark());
        }
    }

    private void publishEvent(ApprovalCallBack.ApprovalCallBackBuilder builder, Long approvalId,
        Boolean approvalFinishFlag, Boolean approvalFlag, String nextApprovalUserId, String nextApprovalUserName,
        Integer eventType, String remark) {
        CallbackEvent callbackEvent =  new CallbackEvent(
                        builder.approvalFinished(approvalFinishFlag).approvalFlag(approvalFlag)
                                .nextApprovalUserId(nextApprovalUserId).nextApprovalUserName(nextApprovalUserName).eventType(eventType)
                                .userId(UserContextHolder.getUserVo().getUserId())
                                .userName(UserContextHolder.getUserVo().getRealName()).remark(remark).approvalId(approvalId).build(),
                        UserContextHolder.getToken());
        TransactionUtils.afterCommit(() -> publisher.publishEvent(callbackEvent));
    }
}
